#include "sgl_draw_arc.h"
#include "sgl_draw_circle.h"
#include "stdio.h"


static void sgl_draw_blend_outedge(sgl_surf_t *surf, int16_t cx, int16_t cy, int16_t r, int16_t angle_start, int16_t angle_end, sgl_color_t fg_color, sgl_color_t bg_color)
{
#if (SGL_CONFIG_DRAW_ALGO == 0)
    int mix = 0;
    int16_t path[SGL_CONFIG_DRAW_STACK_MAX];
    memset(path, 0, SGL_CONFIG_DRAW_STACK_MAX*2);
    int middle = sgl_figure_circle_path(r, path);
    for (int y = 0 ; y < r; y ++) {
        if( y <= middle) {
            mix = (SGL_RENDER_CIRCLE(r, y-1));

            //TODO: add if(...) for deg

            sgl_draw_point(surf, cx + path[y] - 1, cy + y - 1, sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx - path[y], cy + y - 1, sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx + path[y] - 2, cy + y - 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));
            //sgl_draw_point(surf, cx - path[y] + 1, cy + y - 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));

            sgl_draw_point(surf, cx + path[y] - 1, cy - y, sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx - path[y], cy - y, sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx + path[y] - 2, cy - y, sgl_color_mixer(fg_color, bg_color, 256 -  mix));
            //sgl_draw_point(surf, cx - path[y] + 1, cy - y, sgl_color_mixer(fg_color, bg_color, 256 - mix));

            sgl_draw_point(surf, cx - y, cy - path[y], sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx + y - 1, cy - path[y], sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx - y, cy - path[y] + 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));
            //sgl_draw_point(surf, cx + y - 1, cy - path[y] + 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));

            sgl_draw_point(surf, cx + y - 1, cy + path[y] - 1, sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx - y, cy + path[y] - 1, sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx + y - 1, cy + path[y] - 2, sgl_color_mixer(fg_color, bg_color, 256 - mix));
            //sgl_draw_point(surf, cx - y, cy + path[y] - 2, sgl_color_mixer(fg_color, bg_color, 256 - mix));
        }
    }
#else
    int f = 1 - r;
    int diameter = 2*r;
    int ddF_x = 0;
    int ddF_y = - diameter;
    int y = 0;
    int x = r;
    int16_t deg;
    sgl_color_t aa_color;
    while(y < x) {
        if(f >= 0) {
            x--;
            ddF_y += 2;
            f += ddF_y;
        }
        y++;
        ddF_x += 2;
        aa_color = sgl_color_mixer(fg_color, bg_color, - f * 128 / r);
        deg = sgl_fast_atan2(-y, -x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-y, cy-x, aa_color);
        deg = sgl_fast_atan2(-x, -y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-x, cy-y, aa_color);
        deg = sgl_fast_atan2(y, -x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+y-1, cy-x, aa_color);
        deg = sgl_fast_atan2(x, -y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+x-1, cy-y, aa_color);

        deg = sgl_fast_atan2(-y, x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-y, cy+x-1, aa_color);
        deg = sgl_fast_atan2(-x, y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-x, cy+y-1, aa_color);

        deg = sgl_fast_atan2(y, x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+y-1, cy+x-1, aa_color);

        deg = sgl_fast_atan2(x, y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+x-1, cy+y-1, aa_color);

        f += ddF_x + 1;
    }
#endif
}


static void sgl_draw_blend_inedge(sgl_surf_t *surf, int16_t cx, int16_t cy, int16_t r, int16_t angle_start, int16_t angle_end, sgl_color_t fg_color, sgl_color_t bg_color)
{
#if (SGL_CONFIG_DRAW_ALGO == 0)
    int mix = 0;
    int16_t path[SGL_CONFIG_DRAW_STACK_MAX];
    memset(path, 0, SGL_CONFIG_DRAW_STACK_MAX*2);
    int middle = sgl_figure_circle_path(r, path);
    for (int y = 0 ; y < r; y ++) {
        if( y <= middle) {
            mix = (SGL_RENDER_CIRCLE(r, y-1));

            //TODO: add if(...) for deg

            sgl_draw_point(surf, cx + path[y] - 1, cy + y - 1, sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx - path[y], cy + y - 1, sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx + path[y] - 2, cy + y - 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));
            //sgl_draw_point(surf, cx - path[y] + 1, cy + y - 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));

            sgl_draw_point(surf, cx + path[y] - 1, cy - y, sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx - path[y], cy - y, sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx + path[y] - 2, cy - y, sgl_color_mixer(fg_color, bg_color, 256 -  mix));
            //sgl_draw_point(surf, cx - path[y] + 1, cy - y, sgl_color_mixer(fg_color, bg_color, 256 - mix));

            sgl_draw_point(surf, cx - y, cy - path[y], sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx + y - 1, cy - path[y], sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx - y, cy - path[y] + 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));
            //sgl_draw_point(surf, cx + y - 1, cy - path[y] + 1, sgl_color_mixer(fg_color, bg_color, 256 - mix));

            sgl_draw_point(surf, cx + y - 1, cy + path[y] - 1, sgl_color_mixer(fg_color, bg_color, mix));
            sgl_draw_point(surf, cx - y, cy + path[y] - 1, sgl_color_mixer(fg_color, bg_color, mix));
            //sgl_draw_point(surf, cx + y - 1, cy + path[y] - 2, sgl_color_mixer(fg_color, bg_color, 256 - mix));
            //sgl_draw_point(surf, cx - y, cy + path[y] - 2, sgl_color_mixer(fg_color, bg_color, 256 - mix));
        }
    }
#else
    int f = 1 - r;
    int diameter = 2*r;
    int ddF_x = 0;
    int ddF_y = - diameter;
    int y = 0;
    int x = r;
    int16_t deg;
    sgl_color_t aa_color;
    while(y < x) {
        if(f >= 0) {
            x--;
            ddF_y += 2;
            f += ddF_y;
        }
        y++;
        ddF_x += 2;
        aa_color = sgl_color_mixer(fg_color, bg_color, 255 + f * 128 / r);
        deg = sgl_fast_atan2(-y, -x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-y, cy-x, aa_color);
        deg = sgl_fast_atan2(-x, -y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-x, cy-y, aa_color);
        deg = sgl_fast_atan2(y, -x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+y-1, cy-x, aa_color);
        deg = sgl_fast_atan2(x, -y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+x-1, cy-y, aa_color); 

        deg = sgl_fast_atan2(-y, x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-y, cy+x-1, aa_color);
        deg = sgl_fast_atan2(-x, y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx-x, cy+y-1, aa_color);

        deg = sgl_fast_atan2(y, x);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+y-1, cy+x-1, aa_color);

        deg = sgl_fast_atan2(x, y);
        if ((deg >= angle_start) && (deg <= angle_end))
            sgl_draw_point(surf, cx+x-1, cy+y-1, aa_color);

        f += ddF_x + 1;
    }
#endif
}


void sgl_draw_thick_arc(sgl_surf_t *surf, int16_t cx, int16_t cy, int16_t r, int16_t angle_start, int16_t angle_end, int16_t thick, sgl_color_t color, sgl_color_t bg_color)
{
    r += (thick/2);
    uint16_t r2 = r - thick;
    int16_t deg;
    // sgl_pos_t startpoint = sgl_circle_pos_by_angle((r + r - thick)/2, angle_start);
    // sgl_pos_t endpoint = sgl_circle_pos_by_angle((r + r - thick)/2, 90);
    // sgl_draw_circle_solid(surf, cx + startpoint.x, cy - startpoint.y, thick-1, color, bg_color);
    // sgl_draw_circle_solid(surf, cx + endpoint.x, cy + endpoint.y, thick-1, color, bg_color);
    uint32_t rr = r * r;
    uint32_t r2r2 = r2 * r2;
    for(int16_t y = -r; y < 0; y++) {
        for(int16_t x = -r; x < 0; x++) {
            uint32_t r2 = x * x + y * y;
            if ((r2 <= rr) && (r2 >= r2r2)) {
                deg = sgl_fast_atan2(x, y);
                if ((deg >= angle_start) && (deg <= angle_end))
                    sgl_draw_point(surf, cx+x, cy+y, color);
                deg = sgl_fast_atan2(x, -y);
                if ((deg >= angle_start) && (deg <= angle_end))
                    sgl_draw_point(surf, cx+x, cy-y - 1, color);
                deg = sgl_fast_atan2(-x, y);
                if ((deg >= angle_start) && (deg <= angle_end))
                    sgl_draw_point(surf, cx-x-1, cy+y, color);
                deg = sgl_fast_atan2(-x, -y);
                if ((deg >= angle_start) && (deg <= angle_end))
                    sgl_draw_point(surf, cx-x - 1, cy-y - 1, color);
            }
        }
    }
    //to render edge
    sgl_draw_blend_outedge(surf, cx, cy, r, angle_start, angle_end, color, bg_color);
    sgl_draw_blend_inedge(surf, cx, cy, r2, angle_start, angle_end, color, bg_color);
}
